@L }6CD l0C)HCC WhL/h `CmCDiD`  R@P1  Y0@R !L` D  C D     )16CS S)  C)D1 p p 0 C9DI pCDL~CiCDiD`((L;.((L(()6( i( i( ( ( ( 0! :8`ȱ >#<-R+R0 :}(L)`L+)((ȱ A%[! i? <>Ș8?0 L( (H hA ['0 :(L(( (}i:(i((!( 0 ! :(0:())莿((L())H,)* &ՐeԐԥ`ԅ*}ե` BHI Vl)` BHI) Vl)` B Vl)` إ˥ .)l)8}))) )))) G*)))H))) G*h)`B Vl)*+`)) DEIH * } ؐl) ِl)` **) **))-)l) **) **) **) **))ԭ)8)ԥ)eԅԐբP }ԝH՝I)D)EB Vl)LD+P B V`)` B V))I )`)J+,)KBL+S:D+EI }H Vl)``B Vl)``B Vl)`Fatal Error # ))) G*) G*,E9DG,IF,H B } Vl))ԭ)թ)) w*) G*) G*L,Push key to return to DOS,-D,EIH g* ,l H }HHҩҍ2ҩ ҩ<  ҩҍ2ҩҭhhh(`))ˑ)))))))})))))))h)h-)H(ж`טH˄ֱˑh`H))))))))- .))))))))}h)h-)H(мh`ȱȌ)` ..W1;.6/. ((L.Li.Invalid use of command!QD.EIH g*L.Proper fo}rmat is:D.EIH g*L. COPY1 fromfile tofileD.EIH g*.`(֭(נ֙.(֭ (נ֙}'.ߍ)0) JKBD.E7/20IH Vl))1)0JKB'D.EIH Vl)}ԭ8 .ԥ .8.ԥ.եԍ.Ս.)0) 1EWD.I.HB Vl))0)01EWD.I}.H B Vl)L/J)0)01EWD30.1iIhH B Vl) B V0 B V.`HL0Error while }reading filenD0EIH g*hLH,HL0Error while writing fileD0EIH g*hLH,HL1Could not open D0EIH g*hLH,HL;1Could not op/1V1en #D1EIH g*hLH,ȱ >#<-R+R0 :dd*ACOPY1 -- A SINGLE FILE COPY PROGRAMAeX;f9X; before the first page, we give some printer optionsgX;hELiEK}j)=x;; line length is 120 charactersk*=;; indent all except error lines!l:X; NOTE: you may need to put the charac}ter sequence form6X; "condensed print" into the .TITLE line if yourn4X; printer cannot print 120 characters per lineo}X; in default mode.pX;q"A. SOME GENERAL REMARKSArX;sX; copy one file only. It is intended as a demonstrationu=X; of the capabilities of CPARSE and the MAC/65 ToolKit.v}X;w:X; This program is intended to be used from the commandxX; Note that if you do NOT give a device specifier followed};X; by a colon (e.g., P: or D2:), the OSS CP (as called=X; by CPARSE in this program) will automatically prepend;X; } "Dn:", where "n" is the same as the current prompt.AX; (See your OS/A+ or DOS XL manual for more on this topic.)X; }X;AX; This program makes use of much of the information publishedAX; in the OS/A+ and DOS XL manuals, in particular as!} regards2X; IOCB's and values returned from DOS calls.X;X; The program:X;>X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"};;;;;;;;;;;;;;;;;;;;;;;X;DA. System Equates (not printed) and COPY1 fixed RAM usageAX; 10CPALOCX;6X; #}this code is only assembled on Pass 1, thanks toX; the above .IF usage.X;>D:SYSEQU.M65>D:KERNMAC.M65X;$}X;4X; But then we turn off the KERNEL macros' saving.X; of X and Y registers (because we don't/X; count on the%}m not changing), especiallyX; in I/O macros.X;@@PUSHREGS;; thusX;:X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;&};;;;;;;;;;;;;;;;X;:X; First, we jump around CPARSE and the kernel routines4X; so that we can make this a .COM file f'}or use&X; by the CP of OS/A+ and DOS XL.X;>X; ======= change this to match your system's LOMEM =======X;((}X;X; COPY1!ACTUAL.STARTX;X;:X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X;*A. )}CPARSE is INCLUDEd from diskA>D:CPARSE.M65X;4A. KERNEL routines are INCLUDEd from diskAX;#X; but we don*}'t want them LISTedX;EI>D:KERNCODE.M65IX;,A. Equates, etc., unique to COPY1AX;)X; The actual+} start of the COPY1 code!X;X;0X; EQUATES and MACROS unique to this program!X;X; first: equatesX;X; File ,}numbersX; INFILEOUTFILEX;X; only legal errorX;EOF;; END OF FILE ERRORX;!X; just a zero p-}age temporary:X;PTR;; used by MOVENAMEX;X;3X; Elements of ARGV "array" used by this programX;7X; ARGV(.}0) = ARGV = name this program was called viaX;)ARG.INFILEARGV;; same as ARGV(1)*ARG.OUTFILEARGV;; same as /}ARGV(2)X;#X; RAM used exclusively by COPY1X;3BUFFER.BEGIN BUFFER.START;; a little redundant(;(this is necessar0}y to avoid a phase*;error when the MINUS macro calculates;how big the buffer is)X;X;-BUFFER.LENGTH ;; just 1}temporary storage*SAFETY ;; leave 1 KB of memory freeX;-X; a place to keep the entry stack pointerX;SAVESTA2}CK X;/X; buffers which can be used with OPEN macroX;!NAME.INFILE ;; input file#NAME.OUTFILE ;; outp3}ut fileX;X;#X; then, some macros of our own!X; FATAL PUSHY ;; save error code%PRINT = ;; print th4}e message PULLY ;; recover error code+!QQERR;; let ToolKit print error numberX;MOVENAME DPOKE PTR= 5}%>@LP Q@PTR7P 81I@LPX;0X; the EXIT macro assumes that you have saved,X; the entry stack6} pointer in SAVESTACK X;  EXIT $SAVESTACK B :X;X;1X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X7};&A. Beginning of actual codeAACTUAL.START@1&SAVESTACK;; so we can return to DOS any time# CPARSE;; dec8}ipher command lineQARGC;; and we insist on"R>;; ...exactly 3 "arguments"HARGC.BAD;; oops...!ARGC.OK;; all ok9}X; ARGC.BADX; oops...not 3 arguments%PRINT AInvalid use of command!A PRINT AProper format is:A!&PRINT A:} COPY1 fromfile tofileA"$EXIT ;; back to DOS XL or OS/A+#X;$0X; if we get here, there were three arguments%X;&0X; ;}we ignore the first one (it is "D1:COPY1")'X;($X; second one is fromfile (input))#X; third one is tofile (output)*X;+<} ARGC.OK,7X; first, move names into buffers accessible by OPEN-&MOVENAME ARG.INFILE=NAME.INFILE.(MOVENAME ARG.OUTF=}ILE=NAME.OUTFILE/)X; now, open both files...with caution0TRAP ERR.OPENIN1'OPEN INFILE=OPIN==NAME.INFILE2TR>}AP ERR.OPENOUT3*OPEN OUTFILE=OPOUT==NAME.OUTFILE4X;5!X; if here, both files open ok6X;7+X; figure out how big ?}our copy buffer is8X;9!CALC MEMTOP;; free space is:"MINUS BUFFER.BEGIN;; between;%MINUS SAFETY;; buffer and him@}em<;STORE BUFFER.LENGTH;; (with a bit of a safety factor)=X;>$X; now start the actual data copy?X;@GETPUT.LOOPAA}TRAP ERR.BGETB.BGET INFILE=BUFFER.START=BUFFER.LENGTHC-X; simply read in a buffer load of data...DTRAP ERR.BPUB}TE/BPUT OUTFILE=BUFFER.START=BUFFER.LENGTHFX; ...and write it back out.G"!GETPUT.LOOP;; and do it againH2X; (note C}that we do this until we get an error)I4A. Error handlers (including end of file)AJX;KX; ERR.BGET --L8X; we eD}xpect to get an error from BGET eventually.M3X; We presume that we will get an end of fileNX; error (136, $88).OX;E}P ERR.BGETQ)>EOF;; end of file?RHERR.BGET.REAL;; no!SX;T(X; got an end of file on BGET...writeUX; what we got F}and quitVX;WTRAP ERR.BPUTX3BPUT OUTFILE=BUFFER.START=ICBLENINFILEY:X; (the length is obtained from value rG}eturned by BGET)ZX;[X; and we are done!\X;],CLOSE INFILE;; that is, after we close^ CLOSE OUTFILE;; both files_H} EXIT `X;a,X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;bX;c!X; these are the fatal errors!dX;eERR.BGET.REALf&FAI}TAL AError while reading fileAgX;h ERR.BPUTi&FATAL AError while writing fileAjX;kERR.OPENINl'FATAL ACould nJ}ot open AmX;nERR.OPENOUTo%FATAL ACould not open ApX;q/X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;K};;;rX;s$A. The actual copy bufferAtX;u9X; We use all of memory from the end of the program tovX; (MEMTOP) asL} a buffer.wX;xBUFFER.START yX;zRAMAeX;f9X; before the first page, we give some printer optionsgX;hELiEK*/(# 10CPALOC)#X;*#3X; Note that these equates will not be assembled+#-X; if CPALOC has been previously defined,#,X; N} (e.g., if you have .INCLUDEd SYSEQU)-#X;.#/X; Also note that they will not be assembled/#*X; on the second pass of the asO}sembly0##AX; These locations must be accessed indirectly through CPALOC?#"X; i.e.: LDA (CPALOC),Y@#S}X;A#"CPGNFN;; GET NEXT FILE NAMEB#'CPDFDV;; DEFAULT DRIVE (3 BYTES)C#2CPBUFP ;; CMD BUFF NEXT CHAR POINTR (1 BYTE)T}D#CPEXFL ;; EXECUTE FLAGE#,CPEXFN ;; EXECUTE FILE NAME (16 BYTES)F#)CPEXNP;; EXECUTE NOTE/POINT VALUESG#CPFNAMU}!;; FILENAME BUFFERH#RUNLOC=;; CP LOAD/RUN ADRI#)CPCMDB?;; COMMAND BUFFER (60 BYTES)J#,CPGOCMD;; ENTRY POINT FOR DV}O AND MENUK#X;L#;; [ .not .def CPALOC ]M#X;N#*ACPARSE -- OS/A+ command line parserAO#LX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;W};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;P#X;Q#' (m}.OUT). These flags are presumed to#EX; be used in future products associated with 'Redirected I/O'.#X;##X;#X; En}XAMPLE:#END}.DATABEGIN.DATA;; first,#.Q>;; we need to clear all our flags, etc.#CP.CLRLOOP#'PBEGIN.DATA8;; by zeroing all by}tes#1;; of the data area#,ICP.CLRLOOP;; (data area is < 128 bytes)#X;#X; now begins the real work#X;#,# QCPALOC}#*O>CPGNFN;; we are building the address#PCP.GETFN#QCPALOC$O>$1PCP.GETFN;; of the "get file name" rout}ine$X;$IX; now we reset the filename getting process back to start of cmd line$X;$#%>CPBUFP;; offset to buffer ptr$Q}>$P@CPALOC7;; now reset$X; $X; $IX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $X; $!X; The} major loop of CPARSE -- $EX; performed until there are no more file names or flags to get$X;$X;$ CP.LOOP$-%>CPBUF}P;; the current buffer ptr pointer$"Q@CPALOC7;; buffer offset to A$*PCP.SAVBUFP;; then save it for a nonce$' CP.GETFN;;} the address we built up$X;$(%>CPBUFP;; the pointer pointer again$5QCP.SAVBUFP;; recover the former buffer ptr value$2}R@CPALOC7;; did we get more from the CMD line?$FCP.NOMORE;; no...quit now$X;$9X; to here: we got either a filename or }a set of flags$X;$-%>CPFNAM;; the pointer to the name buffer$X; we scan for the colon$ CP.COLON $ Q@CPALOC7!$R> :;;} is this the colon?"$FCP.CFND;; yes#$3;; to next char$$ HCP.COLON%$;;; oops...bad command line?&$:;; carry set says 'OO}PS''$X;($(X; we got the colon...check for flags)$X;*$ CP.CFND+$3,$!Q@CPALOC7;; the possible flag-$R> >;; redirected out}put?.$ FCP.OUT/$R> <;; redirected input?0$ FCP.IN1$R> -;; flags follow?2$FCP.MINUS;; yes3$R> +;; flags follow?4$FCP.}PLUS;; yes5$R> 06$DCP.GOFNAM;; not a digig7$ R> 98$ECP.GOFNAM;; not a digit9$QARGC;; is this first arg?:$'FCP.LOOP};; yes...ignore line number;$X;<$ CP.GOFNAM=$1!CP.FNAM;; if none of those, must be filename>$X;?$%X; CP.NOMORE -- no more} to process@$X;A$)CP.NOMORE,;; simply go back to callerB$':;; ...with carry clear meaning 'OK'C$&ACPARSE -- process < and} > flagsAD$X;E$IX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;F$X;G$3X; CP.IN and CP.OUT -- process} the < and > flagsH$X;I$ CP.INJ$$>FLAG.INFLAG.INOUTK$ !CP.INOUTL$ CP.OUTM$$>FLAG.OUTFLAG.INOUTN$X;O$ CP.INOUTP$}/QARGC;; we get the current file name numberQ$9PFLAG.INOUT9;; and set the redirection flag as neededR$X;S$FX; now fix up c}md buffer ptr in case user did '>file' with no spaceT$X;U$3;; to next char followingV$Q@CPALOC7;; get that charW$R> A;; }is it alpha?X$DCP.IOQUIT;; noY$R> Z;; alpha?Z$ECP.IOQUIT;; no[$HX; next char is alpha, presume it is filename...user }forgot the space\$$%>CPBUFP;; again, the buffer ptr]$-Q@CPALOC7;; get the current buffer offset^$,_$'O>CPCMDB;; include o}ffset to buffer`$%?;; make a buffer ptr out of Y rega$1;; back up one charb$X;c$ CP.IOLPd$'Q@CPALOC7;; get a char from cm}d bufe$R> <;; redirector?f$FCP.ADJUST;; yesg$R> >;; other kind?h$FCP.ADJUSTi$1j$HCP.IOLP;; keep lookingk$X;l$ CP.A}DJUSTm$3;; back to first alpha charn$Co$;p$,S>CPCMDB;; change from buf ptr to offsetq$!GCP.IOQUIT;; shouldn't happenr$"%}>CPBUFP;; ptr to offset agains$/P@CPALOC7;; and we have backed up...we hopet$X;u$X;v$ CP.IOQUITw$!!CP.LOOP;; get next p}arameterx$*ACPARSE -- process the + and - flagsAy$X;z$IX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;};;;{$X;|$7X; CP.MINUS and CP.PLUS -- process '-' and '+' flags}$X;~$ CP.MINUS$Q>;; the 'minus' flag$ HCP.PM$ CP.PL}US$Q>;; the plus flag$X;$ CP.PM$&LARGC;; include the filename count$X;$9X; now process all legit characters foll}owing the flag$X;$ CP.PMLP$3;; to next char$5;; save the flag value$/Q@CPALOC7;; get the possible flag character$0}>;; transfer the character to use it as index$(7;; and recover the flag value to use$(> A;; is it alpha?$&DCP.PMNUM;; no}...check for numeric$(> Z;; is it alpha$4ECP.PMQUIT;; no...and can't be numeric...so quit$X; if to here, is alpha$+}PFLAG.A A9;; so set up the proper flag$#DCP.PMLP;; do another character$X;$$X; if here, possible numeric flag$X;$ }CP.PMNUM$(> 0;; numeric?$DCP.PMQUIT;; no$(> 9;; numeric?$ECP.PMQUIT;; no$)PFLAG.0 09;; yes...so setup the fla}g$ DCP.PMLP$X;$X; end of flag characters$X;$ CP.PMQUIT$1!CP.LOOP;; another flag or name to do...maybe$#ACPARSE} -- process a filenameA$X;$IX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$X;$4X; CP.FNAM -- we} have a valid filename to process$X;$ CP.FNAM$'QARGC;; get cnt of filenames so far$T?;; double, to use as ptr$>;; .}..actually as index$QCP.BUFCNT$,$(O>ARG.BUF;; develop address where$%PARGV9;; ...this argument will be$Q>$O}>ARG.BUF$%PARGV9;; both bytes, of course$X;$.%>CPFNAM;; start of the filename in buffer$/$CP.BUFCNT;; count o}f characters in ARG.BUF$GX; we move characters from CP's internal buffer to our master buffer$X;$ CP.FNLP$Q@CPALOC7;;} get a character$5GCP.FNDONE;; presumably, a RETURN ($9B) character$ R>!;; is it a space or less?$DCP.FNDONE;; yes$(P}ARG.BUF9;; good character...save it$2;; bump counter$3;; and pointer$1)>CPFNAM;; max number of chars we transfer$}HCP.FNLP;; more to do$X;$BX; if to here, either got a non filename char or moved 15 chars$X;$ CP.FNDONE$Q>$&PAR}G.BUF9;; ensure good terminator$+2;; to start of next position in ARG.BUF$#&CP.BUFCNT;; for next file name$X;$0#ARGC;;} and say we have gotten another file!$X;$)!CP.LOOP;; next cmd line name or flag$X;OC has been previously defined,#,X; X@!A. KERNEL SUBROUTINESAAX;B)X;************************************CX;D.X; KERNEL CODE -- RAM and coded su }broutinesE-X; to support kernel macrosFX;G)X;************************************HX;IX; first, RAM usa }geJX;Kd }Pe Pf%>g?L1hT?i Uj TkD?L2l,mOnD?L2o #p?L2q1rH?L1sPt Qu P }v:wX;xX; Divide subroutineyX;z QQRDIV{%>|Q} P~ Q?LA1 TU? R D?LA2 }S #?LA21 H?LA1PQ> P QPԎ:X;X; Get a single byteX; QQGET T }16 >Q>PB9Q>PH9PI9 V ERRCHK :X;X; Put a single byteX; QQPUT T16 > }Q> PB9Q>PH9PI9QQQPASS V ERRCHK :&X; calculate the length of a stringX;X; pri }nt subroutineX; QQPRECQ> PB9 V ERRCHK :X;,X; print an integer number (PRINUM macro)X; Q }QPIN ;;I>FP ;; FP>ASCIIQP˾ QP QQSLEN)QQPASS F?NOERR D?NOERR%> !@QQT }RAP: ?NOERR;QQQPASS SQQLENPQQPASS F?LD3?LD1Q>  PQQPUTBPUT QQPASS=QQPUTB"QQPAS }S H?LD1?LD3%>?LD2Q@7M> PQQPUTB PUSHY PUT QQPASS=QQPUTB PULLY 3 )QQLEN }H?LD2:X;X; input subroutineX;QQINQ>PB9 V ERRCHK :X;X; ININUM supporX; QQIN }INPQQPASSINPUT QQPASS=VPOKE =POKE =  D?NO2ERR !@QQTRAP: ?NO2ERR  } D?NERR2 !@QQTRAP: ?NERR2:X;X; LOAD a file (LOAD macro)X; QQLOADGET =QQPASSGET =QQPA }SSQQQPASS MQQPASS R> F?LE7 %> !@QQTRAP: ?LE7 GET =QQPASS GET =QQPASS } GET =QQPASS GET =QQPASS CALC QQPASS MINUS QQPASS PLUS  $>P Q PH9 Q }PI9 QQQPASS PD9 QQQPASS PE9 Q> PB9  V ERRCHK  &)>;; no error...about to get EOF?  }F?LE8;; yes $!?LE7;; no...get another segment ?LE8CLOSE  : X; X; execute GR subroutine! X;" QQGR# PQQPAS }S$ CLOSE % QQQPASS& M>' N>( L> ) PQQPASS* +OPEN =QQPASS=QQPASS=AS:A+ :, X;- X }; execute DRAWTO subroutine. X;/ QQDRAW0 $>`1 Q>2 PB93  V4 ERRCHK 5 :6 X;7 X; execute FILL subroutine8 X };9 QQFILL: P; $>`< Q>= PB9>  V? ERRCHK @ :A X;B )X; Support for TRAP and error messagesC X;D QQERMSG } AFatal Error #AE QQERMLEN QQERMSGF QQERRG 'QQENUMH POKE QQENUM=I CR J CR K BPUT =QQERMSG=QQE }RMLENL PRINUM =QQENUM=M CR N CR O -PRINT APush key to return to DOSAP STOP Q !@ :R X;S X; suppo }rt for STOP macroT X;U QQSTOPV 6W 5X PUSHX Y PUSHY Z SOUND = = =[ WAIT <\ SOUND ===] ?LF }6^ Q_ R>` H?LF6a PULLY b PULLX c 7d 8e :f X;g X; support for BMOVE macroh X;i QQBMOVj %>k 'QQPASS }l 'QQPASSm ?LG1n Q@7o P@7p DINC q DINC r DINC QQPASSs DEQCMP QQPASS=QQPASSt H?LG1u :v  }X;w X; support for PGMOVE macrox X;y QQPGMVz P{ C| 5} %>~ ' 'ր ?LH1 Q@7 P@7 3 H?LH1 7 ? } : X; X; support for BCLR macro X; QQBCLR C 5 %> 'QQPASS 'QQPASS ?LI1 Q> P@7 DIN }C ˕ DINC QQPASS DEQCMP QQPASS=QQPASS H?LI1 7 ? : X; 'X; QQSLEN -- find length of a string *X; w }hich is terminated by a char with X; MSBit on. X; QQSLEN %> ?LB13 Q@7 I?LB1 3 'QQLEN : coded su tE;%A. Some pertinent remarksA6X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X; KERNEL.M65X;+X}; System support macros and subroutinesX;(X; This file MUST be .INCLUDEd before*X; any of the other libraries are us}eX; in your program.X;6X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;5X; Notice how we include the macr}os ONLY on pass 1%X; of the assembly...thus saving$X; time during the second pass.X;0X; For even greater savings}, you may .INCLUDE4X; the separated forms of this file (KERNEL.MAC*X; and KERNCODE.M65) in your own code*X; follo}wing the example of COPY1.M65X; 10@@PASS.@@PASS;; this is only equated (defined)$;on pass 1, so all the follo}wing#;macros are only read on pass 1X;$A. KERNEL support macrosAX;6X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;};;;;;;;;;;;;;;X;)X; First: a set of support macros used)X; internally by other macros and/or #X; system support s}ubroutines. X; 6X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; -X; PULLY, PULLX, PUSHX, PUSHY, PHR, PLR --)X;} simply save and restore registersX;1X; Note that PHR and PLR are controlled by theX; switch @@PUSHREGS!X;)}@@PUSHREGS;; by default, save regsX;X; PULLY 7? PULLX 7> PUSHX A 5!" PUSH}Y #C$5%& PLR '@@PUSHREGS( PULLY ) PULLX *+, PHR -@@PUSHREGS. PUSHX / PUSHY 012}X;38X; BLT and BGT -- only work on certain ranges of args4X;5 BLT 6D 78 BGT 9D@GT:H ;@GT<=X;>}.X; PLDA -- load an argument which is either?+X; immediate (if < 256) or an address@X;A PLDA B   CQ D}EQ> FGHX;I'X; DCMP, DEQCMP -- used by IF macrosJX;K DCMP LDPOKE QQCMP= MDPOKE QQCMP= N;}O QQQCMPP SQQCMPQ QQQCMPR SQQCMPST DEQCMP UDPOKE QQCMP= VDPOKE QQCMP= W QQQCMPX R}QQCMPY6Z QQQCMP[ RQQCMP\6]7^ PQQCFLG_7` MQQCFLGa5b8cdX;e3X; SGET -- get a string argument }which is eitherf/X; literal (in quotes) or an addressgX;h SGET i  j !  k?STR =l Q>4?ST}RmPD9n Q>5?STRoPE9pQ>qPI9rQ> sPH9tu Q>4 vPD9w Q>5 xPE9y  zDPOKE QQCMP=} { QQQCMP|PH9} QQQCMP~PI9Q>PI9Q>PH9X;(X; T16 -- simply multiply A-r}eg by 16X; T16 T?T?T?T?X;1X; ERRCHK -- used by all I/O to implement TRAPX; ERRCHK )>} IERRK !@QQTRAP:ERRKX;"X; CHAN -- get a channel numberX; CHAN   Q  T16 > $}> X;(X; BPGET -- support for BPUT and BGETX; BPGET  CHAN  Q>5 PE9 Q>4 PD9} Q PI9Q PH9Q> PB9 V ERRCHK A. GRAPHICS macrosAX;0X;;;;;;;;;;;;;;;;};;;;;;;;;;;;;;;;;;;;;;;;;;;;X;-X; GRAPHICS support macros from KERNEL.M65X;0X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;};;;;;;X;X;*X; GR -- same as BASIC GRAPHICS commandX;GR  PHR  PLDA  QQGR PLR X;X;} POS -- set X/Y positionX; POS DPOKE U= POKE T= X;4X; COLOR -- choose a COLOR for a later PLO}T, etc.X; COLOR POKE QQCOLR= X;X; PLOT -- plot a pointX; PLOT POS = PUT =QQ}COLRX;X; SETCOLOR -- same as BASICX;SETCOLOR  PUSHX  PLDA > PLDA  T16 P P}LDA ,OP9 PULLX X;+X; LOCATE -- what color is a given pixelX; LOCATE POS =  }GET =   X; .X; TXTPOS -- position cursor in text windowX; TXTPOS DPOKE = POKE = }X;X; DRAWTO -- draw a lineX; DRAWTO POKE =QQCOLRPOS =  PHR  QQDRAW PLR !X;"$X}; FILL -- fill an area (uses OS)#X;$ FILL % PHR & PLDA ' QQFILL( PLR ) "A. Integer MATH Macro}sA X; /X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; 2X; The math macros which are part of KERNEL.M65 X; /X;;;;;;;};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; X; ,X; CALC -- begin a CALCulation by loading /X; first number into pse}udo-register X; CALC DPOKE =   X; 2X; STORE -- store results of a math calculation X; STORE Q} P  Q P   X; 1X; PLUS -- add a value from memory to register X; PLUS    , Q> } O P D?K # ?K  , Q  O P Q  O P   X; 4X; MINUS -- subtract }a value from pseudo-register X; MINUS    ; Q S>  P Q S> P  ; Q S } P Q S  P   X; 0X; MUL -- multiply pseudo register by a value X; MUL PUSHY  }PLDA  P QQRMUL PULLY   X; .X; DIV -- divide pseudo register by a value X; DIV PUSHY }PLDA  P QQRDIV PULLY   X; #X; RND -- choose a random number X; RND  POKE QQCMP=  ?K} Q  RQQCMP BGT ?K F?K A. I/O MacrosAX;5X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;}X;"X; the I/O macros of KERNEL.M65X;5X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;&X; OPEN -- open a file }to a channelX; OPEN  PHR  CHAN  PLDA PJ9 PLDA PK9Q>PB9 SGET  V} ERRCHK  PLR X;0X; CLOSE -- close a channel (no error check!)X; CLOSE  PHR  CHAN Q> }PB9 V PLR X;-X; GET -- get a single byte from a channelX; GET  PHR  PLDA  QQGET}P  PLR X;)X; PUT -- put a character to a channelX; PUT POKE QQPASS=  PHR  PLDA } QQPUT PLR X;(X; BGET -- get a block from a channelX; BGET  PHR BPGET = = = PLR }X;&X; BPUT -- put a block to a channelX; BPUT  PHR BPGET = = =  PLR X;X; PRINT} -- print a stringX;*X; first, the macro which does the workX; @@PRINT  PHR  CHAN   SGET } =  SGET  QQPREC PLR X;"X; now, the macro the user seesX; PRINT   @@P}RINT =   @@PRINT = @@PRINT = = X;X;$X; CR -- output a CR to a c}hannel4X; If no channel given, output to channel 0 X; CR    PUT = PUT =}X;)X; CLS -- simply output a clear screen#X; character to channel 0X; CLS PUT =}X;4X; PRIN}UM -- print an integer number to a channel.X; within a specified width fieldX; PRINUM  PHR  CALC  } PLDA   PQQPASS! PLDA "PQQPASS# QQPIN$ PLR %&X;',X; INPUT -- input a string from a channel }(X;) INPUT * PHR + CHAN , Q>4 -PD9. Q>5 /PE90  1DPOKE QQCMP= 2 QQQCMP3PH94 Q }QQCMP5PI967Q>8PI99Q>:PH9;< QQIN= PLR >?X;@'X; ININUM -- input an integer numberAX };B ININUM C PHR D PLDA E QQININFQGP H QI P J PLR KLX;M+X; BLOAD -- load a binary  }file to memoryNX;O BLOAD P PHR Q CLOSE ROPEN === S QQLOADT PLR UA. CONTROL macro}sAX;0X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;&X; The control macros of KERNEL.M65X;0X;;;;;;;;;;;;;;;;;;};;;;;;;;;;;;;;;;;;;;;;;;;;X;X;0X; GOSUB -- same as JSR except saves X&Y regsX; GOSUB  PUSHX  PUSHY }  PULLY  PULLX X;X; IFEQ, IFNE, IFGT, IFLT --/X; compare two integer values and branchX; if} condition is metX; IFEQ DEQCMP =  H@THEN!  @THEN IFNE DEQCMP =  F@THEN! } @THEN IFLT DCMP =  I@THEN!  @THEN IFGT DCMP =  I@THEN!  @THEN}X;7X; DOI, LOOPI -- loop control using the 'I' variableX; DOI DPOKE QQLOOP= DPOKE QQLOOP= }Q>4?K PQQLOOP Q>5?K PQQLOOP ?K LOOPI DINC QQLOOP!IFGT QQLOOP=QQLOOP=@}LIQQQLOOP 5QQQLOOP 5:@LIX;7X; DOJ, LOOPJ -- loop control using the 'J' variableX; DO}J DPOKE QQLOOP= DPOKE QQLOOP= Q>4?K PQQLOOPQ>5?K PQQLOOP?K LO}OPJ DINC QQLOOP$IFGT QQLOOP=QQLOOP=@LJQQQLOOP5QQQLOOP5:@LJX;7X; DOK}, LOOPK -- loop control using the 'K' variableX; DOK DPOKE QQLOOP= DPOKE QQLOOP = Q>4?K }PQQLOOPQ>5?K PQQLOOP?K LOOPK DINC QQLOOP$IFGT QQLOOP=QQLOOP =@LKQQQ}LOOP5QQQLOOP5:@LK TRAP VPOKE QQTRAP= p#A. MISCellaneous macrosAqX;r0X;};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sX;t*X; Miscellaneous macros from KERNEL.M65uX;v0X;;;;;;;;;;;;;;;;;;;;;;;;;;};;;;;;;;;;;;;;;;;;wX;x(X; DINC -- increment a word (2 bytes)yX;z DINC {# |H?K} # ~?KX;2X; VP}OKE -- poke an immediate value into a wordX; VPOKE  Q>4 P  Q>5  P X;+X; DPOKE -- could be} better called DMOVEX; DPOKE    Q P  Q  P Q> P Q> P }X; X; POKE -- a single byte pokeX; POKE  PLDA P X;.X; WAIT -- wait a certain number of jif }fiesX; WAIT POKE  = ?KQ H?KX;(X; STOP -- stop until START is pushedX; STOP  !}QQSTOPX;&X; SOUND -- just like BASIC's soundX; SOUND POKE =Q>PҶP2   $> "}  PLDA T?> 2 Q>   PLDA  T16 P PLDA M>L#}P9 PLDA P9X;%X; BMOVE -- move a block of memoryX; BMOVE VPOKE QQPASS= VP$}OKE = VPOKE =  QQBMOVX;9X; PGMOVE -- special move of a single page (256 bytes)X; PGMOVE %}POKE =  PLDA  QQPGMVX;3X; BCLR -- clear (set to zero) a block of memoryX; BCLR VPOKE =&} VPOKE QQPASS=  QQBCLRX;-X; PGCLR -- fast clear of a page of memoryX;X; PGCLR  PUSHY '}POKE = POKE =??L1P@73H?L1 PULLY XX;b1X; End of all macros -- so end of the .I(}F froml2X; line 1022 at the beginning of this listingvX;@!A. KERNEL SUBROUTINESAAX;B)X;*****************)}*******************CX;D.X; KERNEL CODE -- RAM and coded subroutinesE-X; to support kernel macrosFX;G)X;*}************************************HX;IX; first, RAM usageJX;KdPe Pf%>g?L1hT?i Uj TkD?L2l,m/}OnD?L2o #p?L2q1rH?L1sPt Qu Pv:wX;xX; Divide subroutineyX;z QQRDIV{%>|Q0}} P~ Q?LA1 TU? R D?LA2 S #?LA21 H?LA1PQ> P Q1}PԎ:X;X; Get a single byteX; QQGET T16 >Q>PB9Q>PH9PI9 V ERRCHK 2}:X;X; Put a single byteX; QQPUT T16 >Q> PB9Q>PH9PI9QQQPASS V ER3}RCHK :&X; calculate the length of a stringX;X; print subroutineX; QQPRECQ> PB9 V ERRCHK 4}:X;,X; print an integer number (PRINUM macro)X; QQPIN ;;I>FP ;; FP>ASCIIQP˾ QP5} QQSLEN)QQPASS F?NOERR D?NOERR%> !@QQTRAP: ?NOERR;QQQPASS SQQLENPQQPASS F?LD6}3?LD1Q>  PQQPUTBPUT QQPASS=QQPUTB"QQPASS H?LD1?LD3%>?LD2Q@7M> PQQPUTB7} PUSHY PUT QQPASS=QQPUTB PULLY 3 )QQLEN H?LD2:X;X; input subroutineX;QQINQ>PB8}9 V ERRCHK :X;X; ININUM supporX; QQININPQQPASSINPUT QQPASS=VPOKE =P9}OKE =  D?NO2ERR !@QQTRAP: ?NO2ERR  D?NERR2 !@QQTRAP: ?NERR2:X;X; LOAD a file (LOAD:} macro)X; QQLOADGET =QQPASSGET =QQPASSQQQPASS MQQPASS R> F?LE7 %> ;} !@QQTRAP: ?LE7 GET =QQPASS GET =QQPASS GET =QQPASS GET =QQPASS CALC QQPASS <}MINUS QQPASS PLUS  $>P Q PH9 Q PI9 QQQPASS PD9 QQQPASS PE9 Q> PB=}9  V ERRCHK  &)>;; no error...about to get EOF? F?LE8;; yes $!?LE7;; no...get another segment ?LE8CLOSE >} : X; X; execute GR subroutine! X;" QQGR# PQQPASS$ CLOSE % QQQPASS& M>' N>( L> ) PQQPASS?}* +OPEN =QQPASS=QQPASS=AS:A+ :, X;- X; execute DRAWTO subroutine. X;/ QQDRAW0 $>`1 Q>2 PB9@}3  V4 ERRCHK 5 :6 X;7 X; execute FILL subroutine8 X;9 QQFILL: P; $>`< Q>= PB9>  V? ERRCHK @ :AA} X;B )X; Support for TRAP and error messagesC X;D QQERMSG AFatal Error #AE QQERMLEN QQERMSGF QQERRG 'QQENUMH B}POKE QQENUM=I CR J CR K BPUT =QQERMSG=QQERMLENL PRINUM =QQENUM=M CR N CR O -PRINT APush C} key to return to DOSAP STOP Q !@ :R X;S X; support for STOP macroT X;U QQSTOPV 6W 5X PUSHX Y PUSHY Z D}SOUND = = =[ WAIT <\ SOUND ===] ?LF6^ Q_ R>` H?LF6a PULLY b PULLX c 7d 8e :f X;gE} X; support for BMOVE macroh X;i QQBMOVj %>k 'QQPASSl 'QQPASSm ?LG1n Q@7o P@7p DINC q DINC r F}DINC QQPASSs DEQCMP QQPASS=QQPASSt H?LG1u :v X;w X; support for PGMOVE macrox X;y QQPGMVz P{ C| 5} G}%>~ ' 'ր ?LH1 Q@7 P@7 3 H?LH1 7 ? : X; X; support for BCLR macro X; QQBCLR C 5 H}%> 'QQPASS 'QQPASS ?LI1 Q> P@7 DINC ˕ DINC QQPASS DEQCMP QQPASS=QQPASS H?LI1 7I} ? : X; 'X; QQSLEN -- find length of a string *X; which is terminated by a char with X; MSBit on. X; QQSLEJ}N %> ?LB13 Q@7 I?LB1 3 'QQLEN :;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X; KERNEL.M65X;+X4u(%A. Some pertinent remarksA6X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X; KERNMAC.M65X;L}X; System support macrosX;(X; This file MUST be .INCLUDEd before*X; any of the other libraries are useX; in youM}r program.X;6X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X;#A. KERNEL support macrosAX;6X;;N};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;)X; First: a set of support macros used)X; internally by other macO}ros and/or #X; system support subroutines. X; 6X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; -X; PULLY, PULP}LX, PUSHX, PUSHY, PHR, PLR --)X; simply save and restore registersX;1X; Note that PHR and PLR are controlled by theQ}X; switch @@PUSHREGS!X;)@@PUSHREGS;; by default, save regsX;X; PULLY 7? PULLX 7>R} PUSHX A 5!" PUSHY #C$5%& PLR '@@PUSHREGS( PULLY ) PULLX *+, PHR -@@PUSHREGS}S. PUSHX / PUSHY 012X;38X; BLT and BGT -- only work on certain ranges of args4X;5 BLT 6D 78 BGTT} 9D@GT:H ;@GT<=X;>.X; PLDA -- load an argument which is either?+X; immediate (if < 256) or an address@XU};A PLDA B   CQ DEQ> FGHX;I'X; DCMP, DEQCMP -- used by IF macrosJX;K DCMP LDPOKE QQCV}MP= MDPOKE QQCMP= N;O QQQCMPP SQQCMPQ QQQCMPR SQQCMPST DEQCMP UDPOKE QQCMP= VW}DPOKE QQCMP= W QQQCMPX RQQCMPY6Z QQQCMP[ RQQCMP\6]7^ PQQCFLG_7` MQQCFLGa5b8cdX;eX}3X; SGET -- get a string argument which is eitherf/X; literal (in quotes) or an addressgX;h SGET i  j Y}!  k?STR =l Q>4?STRmPD9n Q>5?STRoPE9pQ>qPI9rQ> sPH9tu Q>4 vPD9w Q>5 xZ}PE9y  zDPOKE QQCMP= { QQQCMP|PH9} QQQCMP~PI9Q>PI9Q>PH9[}X;(X; T16 -- simply multiply A-reg by 16X; T16 T?T?T?T?X;1X; ERRCHK -- used by all I/O to imple\}ment TRAPX; ERRCHK )> IERRK !@QQTRAP:ERRKX;"X; CHAN -- get a channel numberX; CHAN  ]} Q  T16 > $> X;(X; BPGET -- support for BPUT and BGETX; BPGET  CHAN ^} Q>5 PE9 Q>4 PD9 Q PI9Q PH9Q> PB9 V ERRCHK A. GRAPHIC_}S macrosAX;0X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;-X; GRAPHICS support macros from KERNEL.M65X;0X;;;;`};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X;*X; GR -- same as BASIC GRAPHICS commandX;GR  PHR  PLDA a} QQGR PLR X;X; POS -- set X/Y positionX; POS DPOKE U= POKE T= X;4X; COLORb} -- choose a COLOR for a later PLOT, etc.X; COLOR POKE QQCOLR= X;X; PLOT -- plot a pointX; PLc}OT POS = PUT =QQCOLRX;X; SETCOLOR -- same as BASICX;SETCOLOR  PUSHX  PLDA >d} PLDA  T16 P PLDA ,OP9 PULLX X;+X; LOCATE -- what color is a given pixele}X; LOCATE POS =  GET =   X; .X; TXTPOS -- position cursor in text windowX; TXTPOS DPOf}KE = POKE = X;X; DRAWTO -- draw a lineX; DRAWTO POKE =QQCOLRPOS =  PHRg}  QQDRAW PLR !X;"$X; FILL -- fill an area (uses OS)#X;$ FILL % PHR & PLDA ' QQFILL( PLR )q}BCOPY1 COMB7COPY1 DEMBbMCPARSE M65B"KERNCODEM65BzKERNEL M65BSKKERNMAC M65BPMGR M65BFSCROLL COMB$FSCROLL DEMB!SCROLL M65BSYSEQU M65B*UNIFY COM "A. Integer MATH MacrosA X; /X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; 2X; The math macros which are r}part of KERNEL.M65 X; /X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; X; X; ,X; CALC -- begin a CALCulation by loadings} /X; first number into pseudo-register X; CALC DPOKE =   X; 2X; STORE -- store results of a matht} calculation X; STORE Q P  Q P   X; 1X; PLUS -- add a value from memory to register X; u} PLUS    , Q>  O P D?K # ?K  , Q  O P Q  O P v}  X; 4X; MINUS -- subtract a value from pseudo-register X; MINUS    ; Q S>  P Qw} S> P  ; Q S  P Q S  P   X; 0X; MUL -- multiply pseudo register by ax} value X; MUL PUSHY  PLDA  P QQRMUL PULLY   X; .X; DIV -- divide pseudo register by a y}value X; DIV PUSHY PLDA  P QQRDIV PULLY   X; #X; RND -- choose a random number X; z} RND  POKE QQCMP=  ?K Q  RQQCMP BGT ?K F?K A. I/O MacrosAX;5X;;;;;;;;;;;;;;;;;;{};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;"X; the I/O macros of KERNEL.M65X;5X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;|};;;X;&X; OPEN -- open a file to a channelX; OPEN  PHR  CHAN  PLDA PJ9 PLDA PK9}}Q>PB9 SGET  V ERRCHK  PLR X;0X; CLOSE -- close a channel (no error check!)X; CL~}OSE  PHR  CHAN Q> PB9 V PLR X;-X; GET -- get a single byte from a channelX; GET } PHR  PLDA  QQGETP  PLR X;)X; PUT -- put a character to a channelX; PUT POKE QQ}PASS=  PHR  PLDA  QQPUT PLR X;(X; BGET -- get a block from a channelX; BGET  PHR }BPGET = = = PLR X;&X; BPUT -- put a block to a channelX; BPUT  PHR BPGET = = }=  PLR X;X; PRINT -- print a stringX;*X; first, the macro which does the workX; @@PRINT  PHR}  CHAN   SGET =  SGET  QQPREC PLR X;"X; now, the macro the user sees}X; PRINT   @@PRINT =   @@PRINT = @@PRINT = = X;}X;$X; CR -- output a CR to a channel4X; If no channel given, output to channel 0 X; CR    PUT }= PUT =X;)X; CLS -- simply output a clear screen#X; character to channel 0X; CLS} PUT =}X;4X; PRINUM -- print an integer number to a channel.X; within a specified width field}X; PRINUM  PHR  CALC  PLDA   PQQPASS! PLDA "PQQPASS# QQPIN$ PLR %&X;',X; INPU}T -- input a string from a channel(X;) INPUT * PHR + CHAN , Q>4 -PD9. Q>5 /PE90  1DPOK}E QQCMP= 2 QQQCMP3PH94 QQQCMP5PI967Q>8PI99Q>:PH9;< QQIN= PLR >?X;@'X; INI}NUM -- input an integer numberAX;B ININUM C PHR D PLDA E QQININFQGP H QI P J PLR K}LX;M+X; BLOAD -- load a binary file to memoryNX;O BLOAD P PHR Q CLOSE ROPEN === S QQLOADT P}LR UA. CONTROL macrosAX;0X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;&X; The control macros of KER}NEL.M65X;0X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X;X;0X; GOSUB -- same as JSR except saves X&Y regsX;} GOSUB  PUSHX  PUSHY   PULLY  PULLX X;X; IFEQ, IFNE, IFGT, IFLT --/X; compare two int}eger values and branchX; if condition is metX; IFEQ DEQCMP =  H@THEN!  @THEN IFNE }DEQCMP =  F@THEN!  @THEN IFLT DCMP =  I@THEN!  @THEN IFGT DCMP} =  I@THEN!  @THENX;7X; DOI, LOOPI -- loop control using the 'I' variableX; DOI DPOKE Q}QLOOP= DPOKE QQLOOP= Q>4?K PQQLOOP Q>5?K PQQLOOP ?K LOOPI DINC QQL}OOP!IFGT QQLOOP=QQLOOP=@LIQQQLOOP 5QQQLOOP 5:@LIX;7X; DOJ, LOOPJ -- loop control }using the 'J' variableX; DOJ DPOKE QQLOOP= DPOKE QQLOOP= Q>4?K PQQLOOPQ>5?K} PQQLOOP?K LOOPJ DINC QQLOOP$IFGT QQLOOP=QQLOOP=@LJQQQLOOP5QQQLOOP}5:@LJX;7X; DOK, LOOPK -- loop control using the 'K' variableX; DOK DPOKE QQLOOP= D}POKE QQLOOP = Q>4?K PQQLOOPQ>5?K PQQLOOP?K LOOPK DINC QQLOOP$IFGT} QQLOOP=QQLOOP =@LKQQQLOOP5QQQLOOP5:@LK TRAP VPOKE QQTRAP= p#A. } MISCellaneous macrosAqX;r0X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sX;t*X; Miscellaneous macros from KERNEL.M65u}X;v0X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wX;x(X; DINC -- increment a word (2 bytes)yX;z DINC {# |H?}K} # ~?KX;2X; VPOKE -- poke an immediate value into a wordX; VPOKE  Q>4 P  Q>5  P }X;+X; DPOKE -- could be better called DMOVEX; DPOKE    Q P  Q  P Q}> P Q> P X; X; POKE -- a single byte pokeX; POKE  PLDA P X;.X; WA}IT -- wait a certain number of jiffiesX; WAIT POKE  = ?KQ H?KX;(X; STOP -- stop until S}TART is pushedX; STOP  QQSTOPX;&X; SOUND -- just like BASIC's soundX; SOUND POKE =Q>}PҶP2   $>   PLDA T?> 2 Q>   PLDA  T16 }P PLDA M>LP9 PLDA P9X;%X; BMOVE -- move a block of memoryX; BMOV}E VPOKE QQPASS= VPOKE = VPOKE =  QQBMOVX;9X; PGMOVE -- special move of a single pag}e (256 bytes)X; PGMOVE POKE =  PLDA  QQPGMVX;3X; BCLR -- clear (set to zero) a block of m}emoryX; BCLR VPOKE = VPOKE QQPASS=  QQBCLRX;-X; PGCLR -- fast clear of a page of memo}ryX;X; PGCLR  PUSHY POKE = POKE =??L1P@73H?L1 PULLY AC.M65X;o QQVBVR bQQHTM QQHTP  QQVM  QQHP  QQVP QQOVP QQPBAS  QQMBAS }QQPFLG  QQMFLG QQSHAP QQPSAV  QQHT QQMASK = =0= QQSMSZ 9QQMSM ===}========@== =0=QQMBIT === PLDX   $> $  PMGR  PH}R  PLDA  QQPMGR PLR  SETVEC VPOKE QQVBVR=    SHAPE  PUSHX  PLDA  T?> Q}>5 PQQSHAP9 Q>4  PQQSHAP9 PULLX  PMCOLR  PUSHX  PLDX  PLDA  T16  PQQCMP} PLDA , OQQCMPP9 PULLX ! PMOVE " PUSHX # PLDX $ PLDA % PQQHP9& PLDA ' P}QQVP9(Q>) PQQPFLG9* PULLX +, MMOVE - PUSHX . PLDX / PLDA 0P91 PLDA 2 PQQVM93Q>}4 PQQMFLG5 PULLX 67 PSIZE 8 PUSHX 9 PLDX :0;A< PLDX =P9> PLDA ? PQQHTP9@ PULLX }AB MSIZE C PUSHX D PLDX E0FAGT?HT?I PQQCMPJ PLDA K,L OQQCMPM>N QQQMSM9O LQQSMSZP P}QQSMSZQP R PLDX S PLDA T PQQHTM9U PULLX VW MPLC X&Y PLDX Z QQQMBIT9[ PLDX \M}9]5^$_7`a MPFC b&c PLDX d QQQMBIT9e PLDX fM9g5h$i7jk PPLC l&m PLDX} n QQQMBIT9o PLDX pM 9q5r$s7tu PPFC v&w PLDX x QQQMBIT9y PLDX zM9{5|$}}7~)X;************************************X; PMGR RUNTIME CODE)X;************************************} QQPMGRPԅ,O>> PQQMBAS2 &QQPBAS2&QQPBAS2&QQPBAS2&QQPBASQ>P}ГQ>>P/Q> %>4QQAPMM $>5QQAPMM \: QQAPMM%>?AL1Q8 PQQPSAV83)> H?AL1}$>?AL2 QQQHP9P9 QQQOVP9 RQQVP9 FQQNPX QQQPFLG9 FQQNPX QQQPBAS9Pέ QQQOVP9Pͯ QQ}QHTP9 PQQHT%>C?AL3P@73 )QQHT H?AL3AT?? QQQSHAP8P˽QQQSHAP8P̿ QQQVP9}P PQQOVP9%>?AL4Q@7P@73 )QQHT H?AL4 QQNPX2(> H?AL2 QQQMFLG FQQRET Q}QQMBASPQ>P??AL8P@73 H?AL8$>?AL5 QQQHTM9 PQQHT QQQVM9P%>?AL6}Q@7 LQQMASK9P@73 )QQHT H?AL62(> H?AL5 QQRET$>?AL7 QQQPSAV9P9Q> PQ}QMFLG PQQPFLG92(> H?AL7 !@QQVBVR:QQVM  QQHP  QQVP QQOVP QQPBAS  QQMBAS 2PPLWPPR&P!Q &ՐeԐԥ`ԅ*ե` BHI Vl} P` BHI P Vl P` B Vl P` إ˥ T Pl P8 PP P PP PHH P Phh P})PHP PHH P PhhhP"QR`B Vl P` PHH P DEIH #Qhh ؐl P ِl} P`HH gP PhhHH gPPhhP- Pl PHH gP PhhHH gPPhhHH gP PhhHH gP Phh Pԭ P8} PԥPeԅԐբPԝH՝I PDRSPEB Vl PLQHHP B Vhh` PHH` B Vhh P)I }PHH`PJ PKBLRS:DREIH Vl Phh``B Vl P``B Vl P`Fatal Error # P}P PHH Phh PHH PhhHHRSTE֝DRIRH B Vl PhhHHPԭPթ P P Phh }PHH Phh PHH PhhHHLSPush key to return to DOSDSEIH Phh Sl HHHҩҍ2}ҩ ҩ<  ҩҍ2ҩҭTThhh(` P Pˑ P P PP PP PPPPP}PPPhPh-PH(ж`טH˄ֱˑh`H P P P P PP PP PPPPPPPPhPh-PH(мh`}ȱȌP`TU   TTTTTUTUT UTTTTTTTT}TJJJTT8TTTT8TTTT mTTTTTTԭTթpȑȑԬTȩBȭȭԩȑȑȑԩAȑԭT}ԭTȑԭ$T%UVT$T%TV \T0T1`إHHHHTԭTխṰT͠TȥԑȥՑ}mTԥiTݭT)WȥԑȥՑ̭TԭThhhhԭTTNT9TTT.TT$TTTTT8TTT}TNTBTTT7TVWTTT'TTTTTTTmTTTNT=TTT2TTTT"TTT}TTTTTNT5TTT*TT TTTTTTTTlTTTTTTTTTTTT}TmTTTTmTTWWTTTlTWXYԩ`թPPPP PX!PPP@PP)"PX#P}YYPPPPPPPPPP8PPPPLuX#PH"PH`PPPPPPPPPP8PPPPLX!P}H PH` pTʎTT@TT`TT\T XYU PHH Phh PHH PhhHHL*YUse joystick to scroll s}creen. DYEIH PhhHHLnYPush START key to stop program.NDYEIH PhhxT)TT \)}Gd#AFine scrolling demonstrationAeX;fX; file: FSCROLL.DEMgX;h&X; Fine scrolling demonstration fori$X; the MA!}C/65 Toolkit diskette.jX;k,X; This program uses the scrolling macrosl(X; and routines contained in the filem*X; SCROLL.M!}65 to perform fine scrollingn*X; under joystick control over an arrayo)X; of character data. Graphics mode 0p)X; is used !}to avoid designing a customqX; character set.rX;s&X; The program proceeds as follows:t'X; 1) The array of characters !}overu)X; which to scroll is set up withv,X; sequentially increasing characterw)X; values (just to fill the !}arrayx%X; with a somewhat meaningfuly*X; pattern. The size of the arrayz)X; is 64x64, but these dimensions!}{*X; may be changed by modifying the|,X; global constants XSIZE and YSIZE.})X; 2) Fine scrolling is initiated !}by~(X; using the macro SCRDIM. This*X; macro expects as parameters the*X; character array dimensions, th!}e+X; addresses of the character array(X; as well as free memory to put*X; a display list, and the desire!}d-X; ANTIC mode in which to display the1X; array. The SCRDIM macro automatically(X; sets the lower righ!}t limit of,X; scrolling. At the same time, the,X; POKE macro is used to specify the$X; speed at which t!}o scroll.,X; 3) The main program loop is enterred(X; which just sets the direction+X; value of joystick zer!}o to be the,X; direction of scroll. At the same)X; time, the START key is polled.+X; If the START key i!}s pressed, the)X; program exits by returning the(X; screen to graphics mode zero,&X; and then performing!} an RTS.X;Aequates and constantsAX;X; constants:X;1XSIZE;; horizontal size of character array/YSIZE!}@;; vertical " " " "X;X;X; hardware locations:X;CONSOLEП-STARTKEY;; START key is l!}ow order bit.(STICK0x;; Location for joystick 0X;X;X; zero page memory:X;8CHPTR;; pointer used for in!}direct access to arrayX;X;"X; and, finally, our own macro!X;BOUNDARY      X;Ase!}tup of character arrayAX;PX;1X; Start of code-- First, fill character array0X; with sequential characters s!}tarting with2X; the value zero. Since the character array0X; is used as screen memory, we are filling(X; it with!} the actual screen codes.X;MAIN!FILLARRAYX;1X; includes of macro and subroutine libraries:X;EI 10@PAS!}S>D:KERNMAC.M65PASS;; PASS 1 DONE>D:KERNCODE.M65>D:SCROLL.M65 I=EK=ELX;X;AFILLARRAYPO!}KE CURCHAR=;; Start with screen value of zero:VPOKE CHPTR=SCREEN;; Point at start of screen arrayX;*X; Loop to !}fill screen array with data:X;DOI =XSIZEDOJ =YSIZEX;1%>;; Store current character value in array.!} QCURCHAR P@CHPTR7X;/DINC CHPTR;; Move to next array position.$#CURCHAR;; And bump screen code.X; LOOPJ!} LOOPI X;AInitiate fine scrollingAX;)X; Begin fine scrolling by calling theX; SCRDIM macro.X;0X; !}ANTIC mode 2, xsize by ysize screen array,+X; DLIST is address to put display list,+X; SCREEN is address of character arr!}ay.+SCRDIM =XSIZE=YSIZE=DLIST=SCREENX;*X; Print instructions (pretty simple!):X;CR ;; Clear text windo!}wCR ,PRINT AUse joystick to scroll screen.A-PRINT APush START key to stop program.AX;X;,X; Main loop: !} Copy joystick 0 value into+X; scrolling direction until START keyX; is pressed.X;HLOOPPOKE SCROLL=STICK0;!}; Use joystick value as scroll direction.QCONSOLE;; Check START keyM>STARTKEY HLOOPX;X;'X; Start key was p!}ressed-- return to*X; graphics mode 0 and return to DOS.X;STOPSCROLL GR :X;"AVariables and array!} storageAX;9CURCHAR ;; Char counter used to fill screen arrayX;-X; Display list memory-- must not cross 1K-X!}; boundary, so start it at 1K boundary.BOUNDARY ,DLIST ;; Reserve 1 page for safety.X;6X; Screen array!}-- individual lines may not cross 4K L>p PJMPBYT00 &MODEPOKE XDIM= POKE YDIM= VPOKE SCRBAS= VPOKE SDSPL= %} QQDSRL SETXY POKE XLOC= POKE YLOC=  QQSXYSTOPSCROLL $OLDVBV %OLDVBV Q>!%} SETVBV"#QQCWID =====$QQCHIG = ====%QQMLIN === == & QQDSRL'DPOKE CSRBA%}S=SCRBAS( $MODE) QQQCWID9* PCWIDE+ QQQCHIG9, PCHIGH- QQQMLIN9. PMLINES/Q>0 PXLOC1 PYLOC2 PVSPEED3 P%}HSPEED4Q>5 PSCROLL6Q>7 PSHSROL8 PSVSROL9 QCWIDE:>;Q><(>= HQQSL2>V?? QQSL2@V?AV?B PSRBY%}TWC QXDIMD;E SSRBYTWF PX0LIMG "X0LIMH QYDIMI;J SMLINESK PY0LIML "Y0LIMM QMLINESNT?O,P OMLINESQ P&}LINESR #LINESS #LINEST #LINESU$X; WRITE BEGINING & END OF D LISTVDPOKE =SDSPLWQ>pX%>YP@7Z3[P@&}7\3]P@7^ %LINES_3`3a3bQ>BcP@7d3eQfP@7g3hQiP@7jQ>k3lP@7m3nP@7o3p&}P@7qQ>Ar3sP@7t QSDSPLu3vP@7w QSDSPLx3yP@7zDPOKE RVBIV=${3DPOKE OLDVBV=VVBLKD;; Sav&}e old vblank vector| %>4QQAUTS} $>5QQAUTS~Q> SETVBV;; SETVBVQ>P QQSL3Q HQQSL3DPOKE 0&}=SDSPLQ>P: QQAUTSX; SAVE 212 & 204 ON STACK-Qԍ5 Q5Q̑5 Q5DPOKE&} =CSRBASDPOKE =SDSPL%> QQTL1 QJMPBYTP@73QԜP@73 QP@7X; ADD XDIM TO 21&}2,Qԣ OXDIMPԥ QO> P3 )LINES HQQTL1X; WRITE LAST MODE LINE QJMPBYTM>WP@&}73QԱP@73 QP@7X; WRITE SHADOWS QSHSROLP;; HSCROL QSVSROLPԺ7 P7&}P̾7 P7P QSCROLLPDIRVDIREQQTNU;; NO UPWARD SCROL #VCOUNT QVSPEED RVCOUNT EQQTNU& }Q> PVCOUNT "SVSROL IQQTNU QYLOC HQQTASNQ> PSVSROL FQQTNU QQTASN QCHIGH PSVSROL "YLO& }C; QCSRBAS SXDIM PCSRBAS EQQTNU"CSRBAS QQTNU X; DOWN ?VDIR EQQTNV #VCOUNT QVSPEED R& }VCOUNT EQQTNVQ> PVCOUNT #SVSROL QCHIGH RSVSROL EQQTNVX; CHECK LIMIT QYLOC RY0LIM HQQTASN2& } QCHIGH PSVSROL HQQTNV QQTASN2Q> PSVSROL #YLOC, QCSRBAS OXDIM PCSRBAS DQQTNV#CSRBAS& } QQTNV X; LEFT?VDIR EQQTNL #HCOUNT QHSPEED RHCOUNT EQQTNLQ> PHCOUNT #SHSROL QCWIDE&} RSHSROL  EQQTNL X; CHECK LIMIT  QXLOC  HQQTASN3  QCWIDE PSHSROL HQQTNL QQTASN3Q> PSHSROL "XLO&}C "CSRBASQ> RCSRBAS HQQTNL"CSRBAS QQTNL X; RIGHT ?VDIR EQQTNR #HCOUNT QHSPEED RHCOU&}NT  EQQTNR!Q>" PHCOUNT# "SHSROL$ IQQTNR%X; CHECK LIMIT& QXLOC' RX0LIM( HQQTASN4)Q>* PSHSROL+ FQQT&}NR, QQTASN4- QCWIDE. PSHSROL/ #XLOC0 #CSRBAS1 DQQTNR2#CSRBAS3 QQTNR4 !@RVBIV:5 QQSXY6 QX0LIM7 RXL&}OC8BGT QQSX19 PXLOC: QQSX1; QY0LIM< RYLOC=BGT QQSX2> PYLOC? QQSX2@DPOKE CSRBAS=SCRBASA %YLOCB &}FQQSXL6C QQSXL4D,E QCSRBASF OXDIMG PCSRBASH DQQSXL5I#CSRBASJ QQSXL5K1L HQQSXL4M QQSXL6NX; ADD IN&} XLOCO,P QCSRBASQ OXLOCR PCSRBASS DQQSXL7T#CSRBASU QQSXL7VX; CLEAR SHADOWSWQ>X PSHSROLY PSVSROLZ&}7!@OLDVBV:;; Exit through old vertical blank vector.ort5X; subroutines. They are heavily interdependent,X; so must $5 #AOSS SYSTEM EQUATES FOR ATARIAX;X; FILE = #DN:SYSEQU.M65X;X;X; I/O CONTROL BLOCK EQUATES$X;)SAV*}EPC ;; SAVE CURRENT ORG+X;.@;; START OF SYSTEM IOCBS3IOCB8X;B.ICHID ;; DEVICE HANDLER IS (SET BY OS)L*IC*}DNO ;; DEVICE NUMBER (SET BY OS)VICCOM ;; I/O COMMAND`ICSTA ;; I/O STATUSj ICBADR ;; BUFFER ADDRESSt*}'ICPUT ;; DH PUT ROUTINE (ADR-1)~ICBLEN ;; BUFFER LENGTHICAUX1 ;; AUX 1ICAUX2 ;; AUX 2ICAUX3*} ;; AUX 3ICAUX4 ;; AUX 4ICAUX5 ;; AUX 5ICAUX6 ;; AUX 6X;(IOCBLEN IOCB;; LENGTH OF ONE IOC*}BX; X; IOCB COMMAND VALUE EQUATESX;COPN;; OPEN!CGBINR;; GET BINARY RECORD CGTXTR;; GET TEXT RECORD*}!CPBINR ;; PUT BINARY RECORDCPTXTR ;; PUT TEXT RECORD(CCLOSE ;; CLOSE 2CSTAT ;; GET STATUS<X; F7X; DE*}VICE DEPENDENT COMMAND EQUATES FOR FILE MANAGERPX;ZCREN ;; RENAMEdCERA!;; ERASEnCPRO#;; PROTECTxCUNP$;;*} UNPROTECTCPOINT%;; POINTCNOTE&;; NOTEX;#X; AUX1 VALUES REQUIRED FOR OPENX;OPIN;; OPEN INPUTOP*}OUT;; OPEN OUTPUTOPUPD ;; OPEN UPDATEOPAPND ;; OPEN APPENDOPDIR;; OPEN DIRECTORYX;X;X; * }EXECUTE FLAG DEFINESX;#EXCYES;; EXECUTE IN PROGRESS"+EXCSCR@;; ECHO EXCUTE INPUT TO SCREEN,%EXCNEW;; EXECUT*!}E START UP MODE6$EXCSUP ;; COLD START EXEC FLAG@X;JX; MISC ADDRESS EQUATESTX;^CPALOC ;; POINTER TO CPh"WARMS*"}T;; WARMSTART (0=COLD)r'MEMLO;; AVAILABLE MEM (LOW) PTR|)MEMTOP;; AVAILABLE MEM (HIGH) PTR1APPMHI;; UPPE*#}R LIMIT OF APPLICATION MEMORY%INITADR;; ATARI LOAD/INIT ADR!GOADR;; ATARI LOAD/GO ADR(CARTLOC;; CARTRIDG*$}E RUN LOCATIONCIOV;; CIO ENTRY ADREOL;; END OF LINE CHARX;*X; CP FUNCTION AND VALUE DISPLACEMENTS#X; *%} (INDIRECT THROUGH CPALOC)X; IE. (CPALOC),YX;"CPGNFN;; GET NEXT FILE NAME'CPDFDV;; DEFAULT DRIVE*&} (3 BYTES)2CPBUFP ;; CMD BUFF NEXT CHAR POINTR (1 BYTE)CPEXFL ;; EXECUTE FLAG,CPEXFN ;; EXECUTE FILE NAME (16*'} BYTES)&)CPEXNP;; EXECUTE NOTE/POINT VALUES0CPFNAM!;; FILENAME BUFFER:RUNLOC=;; CP LOAD/RUN ADRD)CPCMDB?;;*(} COMMAND BUFFER (60 BYTES)NCPCMDGOXX;bSAVEPC;; RESTORE PClX;X;X;X; I/O CONTROL BLOCK EQUATES$X;)SAV(JHH NRhh`ʎTT@TT`TT\T XYU PHH Phh PHH PhhHHL*YUse joystick to scroll s0=8`)Portions (c)1983 Action Computer Services  B JKIHiDiELV.+}` C0 BLV`L00l L0 &`hihiHHȱȱL0c .,}!#3`L0JJJJ` x0L0 +0L0 30L0 90H8`HhHh 21L0 .-}BHI V䅠L0 Lg1`ťƤe8夰L1 Ƥ8..}`ŦeѠe桊L1`yright (c) 1984L02 022i2iI:2i2iI:Lw22./}22 1L2 ,2 +2,2 +22 1222i22 12i22 @e2i2.0}2i2i2i2i2ȑ2i 2i22 V2i2i`E2m?2LU3 0M3M3 .1}@e2i22i2i2i2iO3ȑN32i2iQ3ȑP3M3 V2i2i.2}`L4WL3 033 @e2i22i2i 2i2i3ȑ32i2i3ȑ33 .3} V2i2i`Copyright (c) 1984 O.S.S., Inc.4( . .>8 .L444 1 144 14`L44.4} R3ɀL4`4I 4IL544444 R384444i4i4`LG54m44m4.5}44 R3ɀL5L5Read error on input file5w 444444m444m44`L54 4L5L5BUG! No chun.6}k to write.5 44 3ɀL'6L 6Write error on output file6 44444 3ɀLj6Lc6Write erro.7}r on output file6H 4` ,a~ i` pc V^ 6`ɛ,H aLbhA[ ]L6484444L6 Input f.8}ile: 6 %16k F1L6 Output file: 6 %16 F1 1 16k -2ɀLC7L<7Can't open input file7& 46.9} -2ɀLz7Ls7Can't open output file7\ 4 1 144 4IL/84͟444L7L7Segment too large!7 4.:}4m44m44Ů4寐 4i4i4E 4EL)84 4L8 5444444 D5L7 5 1 1``6LV,z